#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "udp-client.h"

#define USED_UDP_FLAGS 0x55

#define UDP_DYMATIC_ALLOC
#ifdef UDP_DYMATIC_ALLOC
static UDP_CLIENT_ENTRY *new_udp_entry()
{
	UDP_CLIENT_ENTRY* tmp; 
	int i = 0;
	
#if 0
	if (udp_clients_mng.used_num >= 128)
		return NULL;
	
	for (i=0;i<128;i++)
	{
		if (udp_clients_mng.udp_entry[i].used == 0)
		{
			udp_clients_mng.udp_entry[i].used = 1;
			udp_clients_mng.used_num++;
			return &udp_clients_mng.udp_entry[i];
		}
	}
#else
	tmp = malloc(sizeof(UDP_CLIENT_ENTRY));
	if (tmp == NULL)
		return NULL;
	memset(tmp,0,sizeof(UDP_CLIENT_ENTRY));
	tmp->used = USED_UDP_FLAGS;
#endif	
	return tmp;
}


static void free_udp_entry(UDP_CLIENT_ENTRY *udp_entry)
{
#if 0
	udp_entry->used = 0;
	udp_clients_mng.used_num--;
	memset(udp_entry,0,sizeof(UDP_CLIENT_ENTRY));
#else
	if (udp_entry->used != USED_UDP_FLAGS)
	{
		printf("invalid udp entry\n");
	}
	else
	{
		free(udp_entry);
		udp_entry = NULL;
	}
#endif
}
#else
UDP_CLIENT_MNG udp_clients_mng;

static UDP_CLIENT_ENTRY *new_udp_entry()
{
	UDP_CLIENT_ENTRY* tmp; 
	int i = 0;
	
	if (udp_clients_mng.used_num >= 128)
		return NULL;
	
	for (i=0;i<128;i++)
	{
		if (udp_clients_mng.udp_entry[i].used == 0)
		{
			udp_clients_mng.udp_entry[i].used = USED_UDP_FLAGS;
			udp_clients_mng.used_num++;
			return &udp_clients_mng.udp_entry[i];
		}
	}
	
	return tmp;
}


static void free_udp_entry(UDP_CLIENT_ENTRY *udp_entry)
{
	if (udp_entry->used != USED_UDP_FLAGS)
	{
		printf("invalid udp entry\n");
		return 
	}
	udp_entry->used = 0;
	udp_clients_mng.used_num--;
	memset(udp_entry,0,sizeof(UDP_CLIENT_ENTRY));
}
int init_udp_mng()
{
	memset(&udp_clients_mng,0,sizeof(UDP_CLIENT_MNG));
	return 0;
}
#endif
/*used by clients*/
UDP_CLIENT_ENTRY *create_udp_client(unsigned char *ip,int port)
{
	int sockfd;
	struct hostent *he;
	printf("create_udp_client %s:%d\n",ip,port);
	UDP_CLIENT_ENTRY *udp_entry =NULL;
	udp_entry = new_udp_entry();
	if (udp_entry == NULL)
	{
		printf("create_udp_client error\n");
		return NULL;
	}
	
	if ((he = gethostbyname(ip))==NULL)
	{
		printf("gethostbyname()error\n");
	 	return NULL;
	}
	
	if ((sockfd=socket(AF_INET, SOCK_DGRAM,0))==-1)
	{
		printf("socket() error\n");
		return NULL;
	}
	
	udp_entry->udp_client.fd = sockfd;
	udp_entry->udp_client.server.sin_family = AF_INET;
	udp_entry->udp_client.server.sin_port = htons(port);
	udp_entry->udp_client.server.sin_addr= *((struct in_addr *)he->h_addr);

	return udp_entry;
}

int destory_udp_client(UDP_CLIENT_ENTRY *udp_entry)
{
	if (udp_entry ==  NULL)
		return 0;
	close(udp_entry->udp_client.fd);
	free_udp_entry(udp_entry);

	
	return 0;
}

/*used by server*/
UDP_CLIENT_ENTRY *clone_udp_client(int fd,struct sockaddr_in *peerfd)
{
	UDP_CLIENT_ENTRY *udp_entry =NULL;
	udp_entry = new_udp_entry();
	if (udp_entry == NULL)
	{
		printf("clone_udp_client error\n");
		return NULL;
	}

	udp_entry->udp_client.fd = fd;
	memcpy(&udp_entry->udp_client.server,peerfd,sizeof(struct sockaddr_in));
	
	return udp_entry;
}

int clear_udp_client(UDP_CLIENT_ENTRY *udp_entry)
{
	if (udp_entry ==  NULL)
		return 0;
	//close(udp_entry->udp_client.fd);
	free_udp_entry(udp_entry);
	
	return 0;
}


int udp_send_msg(UDP_CLIENT_ENTRY *udp_entry,uint8_t *buff,int size)
{
	int num = 0;
	num = sendto(udp_entry->udp_client.fd, buff,size,0,(struct sockaddr *)&udp_entry->udp_client.server,sizeof(struct sockaddr_in));
	if  (num < 0)
	{
		printf("send pkt failed\n");
		return -1;
	}
	udp_entry->stat.txbytes += num;
	return num;
}

int udp_get_msg(UDP_CLIENT_ENTRY *udp_entry,uint8_t *buff,int size,int *retsize)
{
	int num = 0;
	if((num=recvfrom(udp_entry->udp_client.fd,buff,size,0,(struct sockaddr *)&udp_entry->udp_client.peerfd,retsize))== -1)
	{
		printf("recvfrom() error\n");
		return -1;
	}
	udp_entry->stat.rxbytes +=num;
	return num;
}


#if 0
int main(int argc, char *argv[])
{
	 int sockfd, num;
	 char buf[MAXDATASIZE];

	 
	 while (1)
	 {
		 if((num=recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr *)&peer,&addrlen))== -1)
		 {
			 printf("recvfrom() error\n");
			 exit(1);
		 }
		 if (addrlen != sizeof(server) ||memcmp((const void *)&server, (const void *)&peer,addrlen) != 0)
		 {
			 printf("Receive message from otherserver.\n");
			 continue;
		 }

		 buf[num]='\0';
		 printf("Server Message:%s\n",buf);
		 break;
	 }

	 close(sockfd);
}
#endif
